SageMaker Ground Truthのパフォーマンス可視化を調査した
NTT東日本の中村です。
SageMaker Ground Truthのパフォーマンスの可視化について、調査しました。
SageMaker Ground Truthの概要
SageMaker Ground Truthは、教師データを効率良く作成するサービスです。数百、数千に及ぶ教師データを作成する際、複数のワーカー(作業者)を割り当て、ブラウザ経由で、Annotation(教師データ)の作成・レビュー・評価を行います。
こういったサービスはアノテーションツール(サービス)と呼ばれており、OSSで自分で教師データ作成を行えるものから、クラウドベースで教師データの作成を依頼できるものなど、幅広い手法が用意されています。
やっていること
機械学習の為に教師データを必要としており、SageMaker Ground Truthを使用し、動画から静止画のフレームを抽出しして、Amazon Cognitoに登録された社内メンバーにアノテーションの作業をお願いしていました。
社内メンバーはブラウザ経由で静止画を表示して、対象のオブジェクトにBouding Boxを設定していきます。 (画像はイメージです)
この作業が数十枚〜数百枚あり、実際は1つの画像に50~100のBoundingBoxを設定していくため 非常に時間の掛かる作業になります。
今回のアノテーション
- ビデオフレームのオブジェクト検出(Bounding Box)
- 動画ファイルをGround Truth に渡し、静止画として切り出したものを、ラベル付けしている
- 非ストリーミングラベル付けジョブである
- ワーカーはprivate Workforceである
という前提で調査しています。
困っていたこと
進捗を管理したいとなったとき、SageMaker Ground Truthのジョブで進行具合を確認できます。この画像です。
「12本の動画のうち、10本の動画が完了した」ことを表しているのですが 「個々の動画の中の静止画がどのくらい処理されたのか」「誰が処理したのか」等の情報をUIから得ることができません。
もう少し詳しく状況を把握したいと思い、Ground Truthのドキュメントから、出来ることを調査しました。
ジョブとタスクの調査
ジョブ
ジョブは、ラベル付けプロジェクト全体を表す単位です。複数の静止画や動画など、ラベル付けの対象を登録することができます。 ワーカーはこのジョブに参加し、ラベル付けを行います。
ジョブの作成方法ですが、 S3のバケットを指定すると、存在する動画ファイルを全て検出し、自動で静止画のスライスを行います。 オプションで、動画ファイルからスライスするフレームの単位を指定し、任意の秒数で切り出すことで、切り出す静止画の枚数を制御できます。 例えば、30fpsの動画であれば、300フレームごとに切り出すことで、10秒ごとの静止画の切り出しを設定します。 切り出した静止画は、ジョブに登録されます。
今回は、一つのラベリングジョブに複数の動画(からスライスした静止画)がひも付きます。
「データセットオブジェクト」は、親となる動画を指し、「データオブジェクト」は、静止画を示します。
ジョブのAPI
- CreateLabelingJobs
- ListLabelingJobs
- DescribeLabelingJob
- ListLabelingJobsForWorkteam
ジョブの作成や、詳細情報を取得できます。
ジョブの管理
CloudWatch Eventsを使用して、ジョブのステータスが変わった時にイベントを取得できます。 信頼ポリシーを追加したIAMと、aws events put-ruleコマンドによるイベントルールの作成が必要です。
ジョブの完了時、Cloudwatchで下記のイベントを取得できます。
LabelingJobStatus = Completedで、ジョブが完了したことを表しています。
{ "version": "0", "id": "ff6a4ba0-b8f3-9b4a-e71a-606b0f042192", "detail-type": "SageMaker Ground Truth Labeling Job State Change", "source": "aws.sagemaker", "account": "hogehoge", "time": "2024-04-21T05:49:11Z", "region": "ap-northeast-1", "resources": [ "arn:aws:sagemaker:ap-northeast-1:hogehoge:labeling-job/20240410-gray" ], "detail": { "LabelingJobStatus": "Completed" } }
ジョブの開始・終了のイベントはあると便利ですが、ワーカーの個々の進捗を図る、という目的には粒度が大きすぎるため、やはりタスクのステータスが欲しくなります。
タスク
タスクは、個々のワーカーに割り当てられるラベル付けの作業単位です。 Ground Truthは、ジョブに紐づいた静止画等のデータオブジェクトをタスクに小さく分割し、ワーカーに割り当てます。 タスクは、ワーカーが一度に処理できる分量のデータを含むように(詰め込みすぎないように)設計されています。
タスクの注意点ですが、親となる動画から作成された静止画の枚数が少ない場合、分割されたタスクに含まれる静止画も少なくなってしまいます。 よってタスクに含まれている静止画の数は一定ではない=タスクの数と労働の量は必ずしも比例しません。 このため、タスクの消化数だけで作業量を図るのが難しくなっています。
また、このタスクについては、APIが存在しないので
- どういったタスクが発生しているか
- そのタスクにどのくらいのデータオブジェクトが詰め込まれたのか
- そのタスクは誰が実行しているのか
の確認ができないため、API経由でチェックを行うのは難しそうです。
タスクの管理
特に設定を行わなくても、Cloudwatch Logsにワーカーのタスク単位のイベントが出力されます。 より詳細にイベントを追うことができますが、あくまでタスク単位であり、「タスク内のどの静止画を処理したか」レベルの細かいイベントは出力されません。 cognito_sub_idが出力されているので、cognitoからユーザ情報を辿ることもできます。
{ "worker_id": "private.ap-northeast-1.322634f12596f420", "task_accepted_time": "2024-04-25T08:01:12.600", "task_submitted_time": "", "task_returned_time": "", "task_declined_time": "", "workteam_arn": "arn:aws:sagemaker:ap-northeast-1:hogehoge:workteam/private-crowd/inspection", "labeling_job_arn": "arn:aws:sagemaker:ap-northeast-1:hogehoge:labeling-job/inspection", "work_requester_account_id": "hogehoge", "job_reference_code": "ZfAWcikVoaT3geyO", "job_type": "Private", "event_type": "TasksAccepted", "event_timestamp": "1714032072", "cognito_user_pool_id": "ap-northeast-1_wx6tBkp7R", "cognito_sub_id": "e0403866-990a-4eff-8eb6-cc0fb5d83c9e", "oidc_sub_id": "", "oidc_issuer_url": "" }
event_typeで、タスクのステータスを確認できます。
- TasksAccepted:タスクを開始した
- TaskSubmitted:タスクを完了として送信した
- TaskReturned:タスクを(時間が無いなどの理由で)作業中のものを破棄して、返却した(他のワーカへ再割当される)
- TaskDeclined:タスクを拒否した(不適切なタスクと判断したことになり、他のワーカへ再割当されない)
実績のある完了は、event_type = TasksSubmittedとなるので、これをカウントすると良さそうです。 前述の通り、タスクの数と労働の量は完全には比例しないのですが、得られる情報としてはここが限界と思われます。
以上を踏まえて、可視化の方法です。
可視化
以上を踏まえて、可視化の方法です。
ログメトリクス
お手軽に可視化したい場合、Amazon CloudWatchメトリクスが用意されており、ステータスを確認できます。 下のグラフは、時系列でタスクの消化数を可視化しています。
BIツールで可視化
個人的にはLookerStudioをよく使いますが、今回はAWS内で完結させるべく、QuickSightで進めます。
Cloudwatch Logsのイベントログを、CSVに変換していきます。
#!/bin/bash LOG_GROUP_NAME="/aws/sagemaker/groundtruth/WorkerActivity" OUTPUT_FILE="output.csv" aws logs describe-log-streams --log-group-name $LOG_GROUP_NAME --query 'logStreams[].[logStreamName]' --output text | while read STREAM; do aws logs get-log-events --log-group-name $LOG_GROUP_NAME --log-stream-name $STREAM --query 'events[].[message]' --start-from-head --output text done | jq -Rrs '[ split("\n") | .[] | select(length > 0) | fromjson ] | (map(keys) | add | unique) as $cols | map(. as $row | $cols | map($row[.])) as $rows | $cols, $rows[] | @csv'> $OUTPUT_FILE
変換後のCSV
変換したCSVを、QuickSightのデータセットとしてアップロードします。
全レコードを格納した上で、フィルタでevent_type=TaskSubmittedのみに限定して、グラフを表示できました。
7人くらいで作業するはずだったのですが・・・おかしい・・3人しか作業していない・・・のようなことも分かりますね。 今回はタスクの消化数にフォーカスしましたが、平均的なタスク消化時間や、タスクの中断率も可視化できそうです。
まとめ
SageMaker Groud Truthのパフォーマンス可視化について調査を行いました。 ジョブ、タスクの管理はCloudwatch経由で情報を取得でき、CloudwatchメトリクスやBIツールで、可視化を行うことができます。 それより細かい粒度(データオブジェクトを何枚処理した?等)は追跡できないのが現状と思われました。
ラベル付け大変な作業をお願いすることになるので、ワーカーと良いコミュニケーションが行えるよう、可視化の環境も整えていきたいですね。